package eliauk.fun.flowabledemo.controller;

import cn.hutool.core.lang.Assert;
import eliauk.fun.flowabledemo.FlowableConstant;
import eliauk.fun.flowabledemo.config.MyDefaultProcessDiagramGenerator;
import eliauk.fun.flowabledemo.dto.ApproveDto;
import eliauk.fun.flowabledemo.dto.form.LeaveForm;
import eliauk.fun.flowabledemo.service.FlowService;
import eliauk.fun.flowabledemo.service.FlowServiceFactory;
import eliauk.fun.flowabledemo.service.MyTaskService;
import eliauk.fun.flowabledemo.vo.CommentVo;
import eliauk.fun.flowabledemo.vo.Person;
import eliauk.fun.flowabledemo.vo.TaskVo;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("leave")
public class LeaveFlowController extends FlowServiceFactory {

    @Autowired
    private FlowService flowService;

    @Autowired
    private MyTaskService myTaskService;

    @PostMapping("deploy")
    public String deploy(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) {
        try {
            flowService.deploy(name, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "部署成功";
    }


    @PostMapping("start")
    public String startProcess(@RequestBody LeaveForm form) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("days", form.getDays());
        variables.put("leaveForm", form);
        runtimeService.startProcessInstanceById(form.getProcessInstanceId(), variables);
        return "请假流程启动成功";
    }


    @PostMapping("/approve")
    public String completeTask(@RequestBody ApproveDto approveDto) {
        // 参数校验
        Assert.notNull(approveDto.getTaskId());
        Task task = taskService.createTaskQuery().taskId(approveDto.getTaskId()).singleResult();
        Assert.notNull(task, "任务不存在或者已经审核完成");


        // 审批添加批注
        taskService.addComment(task.getId(), task.getProcessInstanceId(), "taskResult", approveDto.getResult().toString());
        taskService.addComment(task.getId(), task.getProcessInstanceId(), "taskComment", approveDto.getComment());
        if (approveDto.getResult()) {
            taskService.addComment(task.getId(), task.getProcessInstanceId(), "taskResultMessage", "通过");
        } else {
            taskService.addComment(task.getId(), task.getProcessInstanceId(), "taskResultMessage", "驳回");
        }

        // 审批完成
        HashMap<String, Object> variables = new HashMap<>();
        variables.put(FlowableConstant.CHECK_RESULT, approveDto.getResult());
        taskService.complete(task.getId(), variables);
        return "审批完成";
    }


    @GetMapping("getTask/{taskId}")
    public TaskVo getTask(@PathVariable String taskId) {
        Assert.notNull(taskId, "任务ID不能为空");
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        Assert.notNull(task, "任务不存在");

        // 这里注意不能直接返回Task，Task 是个接口，需要转换为实现类
        TaskEntityImpl taskEntityImpl = (TaskEntityImpl) task;
        Object taskEntity = taskEntityImpl.getPersistentState();

        TaskVo taskVo = new TaskVo();
        taskVo.setTask(taskEntity);
        // 任务 审批信息
        List<String> commentTypes = Arrays.asList("taskResult", "taskComment", "taskResultMessage");
        List<CommentVo> commentVos = new ArrayList<>();
        for (String type : commentTypes) {
            List<Comment> comments = taskService.getTaskComments(task.getId(), type);
            for (Comment comment : comments) {
                CommentVo commentVo = new CommentVo(comment);
                commentVos.add(commentVo);
            }
        }
        return taskVo;
    }


    /**
     * 流程申请 流转图片输入流
     */
    @GetMapping(value = "diagram/view")
    public void getFlowDiagram(String procInsId, HttpServletResponse httpServletResponse) throws IOException {

        String procDefId;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(procInsId)
                .singleResult();
        if (processInstance == null) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult();
            procDefId = historicProcessInstance.getProcessDefinitionId();

        } else {
            procDefId = processInstance.getProcessDefinitionId();
        }

        BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);
        MyDefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new MyDefaultProcessDiagramGenerator();

        List<String> highLightedActivities = new ArrayList<>(); // 高亮节点集合
        List<String> highLightedFlows = new ArrayList<>(); // 高亮连线集合
        List<HistoricActivityInstance> hisActInsList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInsId)
                .list(); // 查询所有历史节点信息
        // 过滤掉已被删除的
        hisActInsList = hisActInsList.stream()
                .filter(historicActivityInstance -> historicActivityInstance.getDeleteReason() == null)
                .collect(Collectors.toList());

        hisActInsList.forEach(historicActivityInstance -> {
                if ("sequenceFlow".equals(historicActivityInstance.getActivityType())) {
                    // 添加高亮连线
                    highLightedFlows.add(historicActivityInstance.getActivityId());
                } else {
                    // 添加高亮节点
                    highLightedActivities.add(historicActivityInstance.getActivityId());
                }
        });
        String imageType = "png"; // 生成图片的类型
        String activityFontName = "宋体"; // 节点字体
        String labelFontName = "宋体"; // 连线标签字体
        String annotationFontName = "宋体"; // 连线标签字体
        ClassLoader customClassLoader = null; // 类加载器
        double scaleFactor = 1.0d; // 比例因子，默认即可
        boolean drawSequenceFlowNameWithNoLabelDI = true; // 不设置连线标签不会画
        // 生成图片
        InputStream inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, imageType, highLightedActivities
                , highLightedFlows, activityFontName, labelFontName, annotationFontName, customClassLoader,
                scaleFactor, drawSequenceFlowNameWithNoLabelDI); // 获取输入流

        // 直接写到页面，要先获取HttpServletResponse
        byte[] bytes = IoUtil.readInputStream(inputStream, "flow diagram inputStream");
        httpServletResponse.setContentType("image/png");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        httpServletResponse.reset();
        outputStream.write(bytes);
        outputStream.flush();
        outputStream.close();
    }


    @GetMapping(value = "rollbackTask/{taskId}")
    public String getFlowDiagram(@PathVariable String taskId) {
        myTaskService.rollbackTask(taskId, "no reason");
        return "rollback success";
    }


}
